import React, { useCallback } from 'react';
import { isFunction } from '../utils';
import useRefState from './use-ref-state';
import useUnmountedRef from './use-unmounted-ref';

type Patch<T extends object> = Partial<T> | ((prevState: T) => Partial<T>);

const useSetState = <T extends object>(
  initialState: T = {} as T,
): [T, (patch: Patch<T>) => void, React.MutableRefObject<T>] => {
  const unmountedRef = useUnmountedRef();
  const [state, setState, ref] = useRefState<T>(initialState);

  const setMergeState = useCallback(
    (patch: Patch<T>) => {
      if (unmountedRef.current) return;
      setState((prevState) => ({
        ...prevState,
        ...(isFunction(patch) ? patch(prevState) : patch),
      }));
    },
    [setState, unmountedRef],
  );

  return [state, setMergeState, ref];
};

export default useSetState;
